#pragma once
#include <iostream>
#include <string>
#include <vector>
#include <functional>
#include <memory>
#include <cassert>
#include <cstdio>
#include <unistd.h>
#include <pthread.h>
using namespace std;

class Pthread;

struct Context
{
    Pthread* _this;
    void* _args;

    Context(Pthread* thisx, void* args) :_this(thisx), _args(args)
    {}

};


class Pthread 
{
public:
    typedef function<void*(void*)> func_t;
    const int num = 1024;
public:
    Pthread(func_t fun, void* args, int number) :_fun(fun), _args(args)
    {
        char buffer[num];
        snprintf(buffer, sizeof buffer, "thread->%d",number);
        _name = buffer;

        Context* ctx = new Context(this,_args);
        int n = pthread_create(&_tid,nullptr,start_routine,ctx);
        assert(n == 0);
        (void)n;        
    }

    static void* start_routine(void* args)
    {
        //没有this指针，不能如下调用
        //return _fun(args);

        Context* ctx = (Context*)args;
        void* ret = ctx->_this->_fun(ctx->_args);
        delete ctx;
        return ret;
    }

    void join()
    {
        int n = pthread_join(_tid,nullptr);
        assert(n == 0);
        (void)n;
    }

private:
    string _name;
    func_t _fun;
    void* _args;
    pthread_t _tid;
};